package ro.ubbcluj.cs.validation.framework.tags;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.jsp.JspException;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ro.ubbcluj.cs.validation.framework.core.ParameterName;
import ro.ubbcluj.cs.validation.framework.core.ValidationRule;
import ro.ubbcluj.cs.validation.framework.core.ValidationRuleType;
import ro.ubbcluj.cs.validation.framework.tags.utils.TagUtils;
import ro.ubbcluj.cs.validation.framework.tags.utils.ValidatorTagBuilder;

public class InputTextTag extends BaseTag implements GeneralInputTag {

	private static final long serialVersionUID = -7737953398635401823L;
	private Logger log = LoggerFactory.getLogger(InputTextTag.class);
	
	/**
	 * This map will contains the validation rules, which will be inserted by the validators
	 * ex: (maxlength,20)
	 */
	private List<ValidationRule> validationRules;
	
	/**
	 * name - Specifies a name for an input element
	 */
	private String name;
	
	/**
	 * value - Specifies the value of an input element
	 */
	private String value;
	
	/**
	 * number -	Specifies the width of an input field
	 */
	private int size;
	
	/**
	 * readonly - Specifies that an input field should be read-only
	 */
	private boolean readonly;
	
	/**
	 * disabled - pecifies that an input element should be disabled when the page loads
	 */
	private boolean disabled;
	
	/**
	 * number -	Specifies the maximum length (in characters) of an input field
	 */
	private int maxlength;
	
	public InputTextTag() {
		release();
	}

	@Override
	public int doStartTag() throws JspException {
		if (!(this.getParent() instanceof FormTag)) {
			log.error("Wrong place for the input tag! Input tag can be put only in the form.");
			release();
			return EVAL_PAGE;
		}
		try {
			pageContext.getOut().println("<input type=\"text\" "+getAttributes()+getSpecificAttributes()+"/>");
		} catch (IOException e) {
			log.error("Error printing input tag: " + e.getMessage());
		}
		return EVAL_BODY_INCLUDE;
	}
	
	@Override
	public int doAfterBody() throws JspException {
		try {
			if (StringUtils.isNotEmpty(name)){
				for (String v : ValidatorTagBuilder.buildValidators(TagUtils.getFormName(this), name, validationRules)){
					String eAttrName = v.substring(v.indexOf("validator:"), v.indexOf("\"", v.indexOf("validator:")));
					String errorMsg = (String)pageContext.getRequest().getAttribute(eAttrName);
					if (errorMsg != null) {
						pageContext.getOut().println("<br/><label style=\"color: red;\">"+errorMsg+"</label>");
						pageContext.getRequest().removeAttribute(eAttrName);
					}
					pageContext.getOut().println(v);
				}
			}
		} catch (IOException e) {
			log.error("Error printing validator (input hidden) tag: " + e.getMessage());
		}
		return SKIP_BODY;
	}
	
	@Override
	public int doEndTag() throws JspException {
		release();
		return EVAL_PAGE;
	}
	
	private String getSpecificAttributes(){
		StringBuilder attributes = new StringBuilder();
		if (StringUtils.isNotEmpty(name)) {
			attributes.append("name=\""+TagUtils.getFormName(this)+"inputText:"+TagUtils.normalizeName(name)+"\" ");
		}
		if (StringUtils.isNotEmpty(value)) {
			attributes.append("value=\""+value+"\" ");
		}
		if (size >= 0) {
			attributes.append("size=\""+size+"\" ");
		}
		if (readonly) {
			attributes.append("readonly=\"readonly\" ");
		}
		if (disabled) {
			attributes.append("disabled=\"disabled\" ");
		}
		if (maxlength >= 0) {
			attributes.append("maxlength=\""+maxlength+"\" ");
		}
		return attributes.toString();
	}
	
	public void addValidationRule(ValidationRuleType type, Map<ParameterName, String> parameter){
		this.validationRules.add(new ValidationRule(type, parameter));
	}
	
	public final String getName() {
		return name;
	}

	public final void setName(String name) {
		this.name = name;
	}

	public final String getValue() {
		return value;
	}

	public final void setValue(String value) {
		this.value = value;
	}

	public final int getSize() {
		return size;
	}

	public final void setSize(int size) {
		this.size = size;
	}

	public final boolean isReadonly() {
		return readonly;
	}

	public final void setReadonly(boolean readonly) {
		this.readonly = readonly;
	}

	public final boolean isDisabled() {
		return disabled;
	}

	public final void setDisabled(boolean disabled) {
		this.disabled = disabled;
	}

	public final int getMaxlength() {
		return maxlength;
	}

	public final void setMaxlength(int maxlength) {
		this.maxlength = maxlength;
	}

	@Override
	public void release() {
		super.release();
		this.validationRules = new ArrayList<ValidationRule>();
		this.name = null;
		this.value = null;
		this.size = -1;
		this.readonly = false;
		this.disabled = false;
		this.maxlength = -1;
	}
}
